Conversation
|
[ISSUE #3] Feature/cache layer 와 같은 식으로 ISSUE와 연결해서 PR을 등록해주세요 |
| class Barcode { | ||
| final String value; | ||
|
|
||
| Barcode(String value) : value = value.trim(); |
There was a problem hiding this comment.
| Barcode(String value) : value = value.trim(); | |
| Barcode(String value): value = value.trim(); |
| class BarcodeCacheService { | ||
| final CacheManager _cacheManager = CacheManager(); | ||
|
|
||
| Future<void> saveToCache(String barcode, String data) async { |
There was a problem hiding this comment.
| Future<void> saveToCache(String barcode, String data) async { | |
| Future<void> save(String barcode, String data) async { |
| await _cacheManager.saveToCache(cacheKey, data); | ||
| } | ||
|
|
||
| Future<String?> loadFromCache(String barcode) async { |
There was a problem hiding this comment.
| Future<String?> loadFromCache(String barcode) async { | |
| Future<String?> load(String barcode) async { |
| return await _cacheManager.loadFromCache(cacheKey); | ||
| } | ||
|
|
||
| String _getCacheKey(String barcode) { |
There was a problem hiding this comment.
| String _getCacheKey(String barcode) { | |
| String _getKey(String barcode) { |
| Future<void> startBarcodeScan(BuildContext context) async { | ||
| final barcode = await _scanService.scanBarcode(context); | ||
| try { | ||
| if (barcode != null) { | ||
| _updateScannedBarcode(barcode.value); | ||
| } | ||
| } catch (e) { | ||
| _handleError(e); | ||
| } finally { | ||
| ///디버그 모드일 때에는 촬영이 불가능하여 임의의 바코드 값을 설정한다. | ||
| if (kDebugMode) { | ||
| _updateScannedBarcode('1234567890123'); | ||
| if (context.mounted) { | ||
| await _checkCachedData(context, scannedBarcode); | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
현재 startBarcodeScan()이 포함하고 있는 기능 목록
- 스캔
- 바코드 업데이트
- 에러 처리
- 디버그용 임시 데이터 처리
There was a problem hiding this comment.
startBarcodeScan() : Refactoring
Future<void> startBarcodeScan(BuildContext context)Future<Barcode?> _performBarcodeScan(BuildContext context)Future<void> _handleScannerBarcode(BuildContext context, String barcodeValue) asyncFuture<void> _checkDebugModeCachedData(BuildContext context) asyncvoid _setDebugBarcodeTemp()
There was a problem hiding this comment.
메소드를 더 잘게 나누어 수정했습니다!
| final cachedData = await _cacheService.loadFromCache(barcode ?? ''); | ||
| if (context.mounted) { | ||
| if (cachedData != null) { | ||
| _navigateToIntakeGuide(context, cachedData); | ||
| } else { | ||
| _navigateToNutrientScan(context); | ||
| } | ||
| } |
There was a problem hiding this comment.
context.mounded처럼 조건이 명확하고, 실패할 경우 이후 코드를 진행할 필요가 없을 때는 early return 처리하기!!!
if (!context.mounted) return;
final cachedData = await _cacheService.load(barcode ?? '');
if (cachedData != null) {
_navigateToIntakeGuide(context, cachedData);
} else {
_navigateToNutrientScan(context);
}
lib/util/cache_manager.dart
Outdated
| class CacheManager { | ||
| static const _cacheDuration = Duration(days: 7); | ||
|
|
||
| Future<void> saveToCache(String key, String value) async { |
There was a problem hiding this comment.
| Future<void> saveToCache(String key, String value) async { | |
| Future<void> save(String key, String value) async { |
lib/util/cache_manager.dart
Outdated
| await prefs.setString('${key}_expiry', expiryDate); | ||
| } | ||
|
|
||
| Future<String?> loadFromCache(String key) async { |
There was a problem hiding this comment.
| Future<String?> loadFromCache(String key) async { | |
| Future<String?> load(String key) async { |
lib/util/cache_manager.dart
Outdated
| return null; | ||
| } | ||
|
|
||
| Future<void> removeFromCache(String key) async { |
There was a problem hiding this comment.
| Future<void> removeFromCache(String key) async { | |
| Future<void> remove(String key) async { |
lib/util/cache_manager.dart
Outdated
| final prefs = await SharedPreferences.getInstance(); | ||
| final cachedValue = prefs.getString(key); | ||
| final expiryDateStr = prefs.getString('${key}_expiry'); | ||
|
|
||
| if (cachedValue != null && expiryDateStr != null) { | ||
| final expiryDate = DateTime.parse(expiryDateStr); | ||
| if (DateTime.now().isBefore(expiryDate)) { | ||
| return cachedValue; | ||
| } else { | ||
| // Remove expired cache | ||
| await prefs.remove(key); | ||
| await prefs.remove('${key}_expiry'); | ||
| } | ||
| } | ||
| return null; |
There was a problem hiding this comment.
| final prefs = await SharedPreferences.getInstance(); | |
| final cachedValue = prefs.getString(key); | |
| final expiryDateStr = prefs.getString('${key}_expiry'); | |
| if (cachedValue != null && expiryDateStr != null) { | |
| final expiryDate = DateTime.parse(expiryDateStr); | |
| if (DateTime.now().isBefore(expiryDate)) { | |
| return cachedValue; | |
| } else { | |
| // Remove expired cache | |
| await prefs.remove(key); | |
| await prefs.remove('${key}_expiry'); | |
| } | |
| } | |
| return null; | |
| final prefs = await SharedPreferences.getInstance(); | |
| final cachedValue = _getCachedValue(prefs, key); | |
| final expiryDate = _getExpiryDate(prefs, key); | |
| if (cachedValue == null || expiryDateStr == null) { | |
| return null; | |
| } | |
| if (_isExpired(expiryDate) | |
| await prefs.remove(key); | |
| await prefs.remove('${key}_expiry'); | |
| } | |
| return cachedValue; |
String? _getCachedValue(SharedPreferences pref, String key) {
return prefs.getString(key);
}
Datetime _getExpiryDate(SharedPreferences pref, String key) {
final expireDateStr = prefs.getString('${key}_expiry');
if (expiryDateStr == null) return null;
try {
return Datetime.parse(expireDateStr);
} catch (_) {
return null;
}
}
bool _isExpired(Datetime expiryDate) {
return Datetime.now().isAfter(expiryDate);
}
There was a problem hiding this comment.
BarcodeCacheService는 XXXService이기 때문에, 최대한 비즈니스 디펜던시가 있는 부분을 모두 포함하는 객체라고 생각
| if (kDebugMode) { | ||
| _setDebugBarcodeTemp(); | ||
| if (context.mounted) { | ||
| await _checkCachedData(context, scannedBarcode ?? ''); | ||
| } | ||
| } |
There was a problem hiding this comment.
| if (kDebugMode) { | |
| _setDebugBarcodeTemp(); | |
| if (context.mounted) { | |
| await _checkCachedData(context, scannedBarcode ?? ''); | |
| } | |
| } | |
| if (!kDebugMode) { | |
| return; | |
| } | |
| _setDebugBarcodeTemp(); | |
| await _checkCachedData(context, scannedBarcode ?? ''); |
| if (cachedAnswer != null) { | ||
| return AnalysisResult(cachedAnswer); | ||
| } | ||
| return null; |
There was a problem hiding this comment.
| if (cachedAnswer != null) { | |
| return AnalysisResult(cachedAnswer); | |
| } | |
| return null; | |
| return cachedAnswer != null ? AnalysisResult(cachedAnswer) : null; |
|
피드백 반영하여 코드 다시 정리하였습니다. |
캐싱 관련한 기능을 구현해본 적이 처음이라 캐싱 관련된 코드를 중점적으로 봐주시면 좋을 것 같습니다!